(function($) {

    var CheckAll = function(element, options) {
        var _this = this;

        this.$element = $(element);

        // 全选
        $(options.checkbox).click(function() {
            var checked = $(this).is(":checked");

            // 对于可用的行，更新选择状态
            _this.$element.find('tbody > tr input[type=checkbox]').not(':disabled')
                .prop('checked', checked)
                .parents('tr').toggleClass('selected', checked);

            // 对于选中的不可用的行，移除选择状态
            _this.$element.find('tbody > tr.selected input[type=checkbox]').filter(':disabled')
                .parents('tr').removeClass('selected');
        });

        // 单选
        this.$element.off('click.check').on('click.check', 'tbody > tr', function(event) {
            var $currentCheckbox = $('input[type="checkbox"]', this),
                checked = $currentCheckbox.is(":checked");

            if ( $currentCheckbox.is(event.target) ) {
                $(this).toggleClass("selected", checked);
            }
            else if ( !$currentCheckbox.is(":disabled") ) {
                // 点击TR时可以达到选择的效果
                $currentCheckbox.prop("checked", !checked);
                $(this).toggleClass("selected", !checked);

                // 取消其他复选框
                $(options.checkbox).prop("checked", false);
                _this.$element
                    .find('tbody > tr').not(this).removeClass("selected")
                    .find('input[type="checkbox"]')
                    .prop("checked", false);
            }
        });
    };

    CheckAll.prototype.recheck = function (afterRechecked) {
        $('tbody > tr', this.$element).each(function() {
            var $checkbox = $('input[type="checkbox"]', this),
                checked = $(this).hasClass("selected");

            if ($checkbox.is(":disabled") && checked) {
                // 对于disabled的项，清除选中状态
                $(this).removeClass("selected");
            } else {
                $checkbox.prop("checked", checked);
            }
        });

        afterRechecked.call(this);
    };

    $.fn.checkAll = function(option) {
        var $this   = $(this),
            data    = $this.data('check-all');

        if (typeof option === 'object' && !data) {
            $this.data('check-all', (data = new CheckAll(this, option)));
        }

        if (typeof option === 'string') {
            data[option].apply(data, Array.prototype.slice.call(arguments, 1));
        }

        return this;
    }

})(jQuery);